from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from django.db.models.signals import pre_save
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError, MultipleObjectsReturned, ObjectDoesNotExist
from role.models import Role, UserRole
from dept.models import Dept, UserDept
from tenant.models import Tenant
from utils.utils import SetNone
from frame_server.serializers import BaseSerializer as BSerializer

User = get_user_model()

class LoginValidate(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()
    code =  serializers.CharField()

    def validate(self, data):
        username = data.get('username','')
        password = data.get('password','')
        code = data.get('code','')
        try:
            code2 = self.context['req'].session.pop('code')
        except KeyError:
            raise ValidationError('验证码错误')
        if code != code2:
            raise ValidationError('验证码错误')
        if not User.objects.filter(account=username).exists():
            raise ValidationError('账号不存在')
        user = User.objects.get(account=username)
        if not user.check_password(password):
            raise ValidationError('账号或密码错误')
        return data

# 新增/编辑验证基类
class AddEditValidateBase(BSerializer):
    account = serializers.CharField(max_length=30, validators=[UniqueValidator(queryset=User.objects.all(), message="账号已存在")])
    name = serializers.CharField(max_length=255, validators=[UniqueValidator(queryset=User.objects.all(), message="名称已存在")])
    phone = serializers.IntegerField(required=False, allow_null=True, validators=[UniqueValidator(queryset=User.objects.all(), message="手机号已存在")])
    roleId = serializers.CharField(required=False, allow_blank=True)
    deptId = serializers.CharField(required=False, allow_blank=True)
    tenantId = serializers.CharField(required=False, allow_null=True)

    def validate_roleId(self, val):
        if not val:
            return None
        ids = val.split(',')
        if Role.objects.filter(id__in=ids).count() != len(ids):
            raise serializers.ValidationError("选择角色不存在")
        return ids

    def validate_deptId(self, val):
        if not val:
            return None
        ids = val.split(',')
        if Dept.objects.filter(id__in=ids).count() != len(ids):
            raise serializers.ValidationError("选择部门不存在")
        return ids

    def validate_tenantId(self, val):
        if not val:
            return None
        try:
            obj = Tenant.objects.only('pk').get(pk=val)
        except MultipleObjectsReturned:
            raise serializers.ValidationError("查询到多条租户信息")
        except ObjectDoesNotExist:
            raise serializers.ValidationError("租户不存在")
        return obj
    
    class Meta:
        model = User

# 新增用户
@SetNone(filter=['roleId','deptId'])
class AddUserValidate(AddEditValidateBase):
    password = serializers.CharField(max_length=30)
    password2 = serializers.CharField(max_length=30)
    
    def validate(self, data):
        if data['password'] != data['password2']:
            raise serializers.ValidationError("两次密码不一致")
        return data
    
    def create(self, data):
        data.pop('password2', None)
        roleId = data.pop('roleId', None)
        deptId = data.pop('deptId', None)
        user = super().create(data)
        user.set_password(data['password'])
        user.save()
        if roleId:
            for i in UserRole.objects.bulk_create([UserRole(user=user,role_id=id) for id in roleId]):
                i.save() # 为了触发信号
        if deptId:
            for i in UserDept.objects.bulk_create([UserDept(user=user,dept_id=id) for id in deptId]):
                i.save() # 为了触发信号
        return user
    
    class Meta(AddEditValidateBase.Meta):
        fields = '__all__'

# 编辑用户
@SetNone(filter=['roleId','deptId'])
class EditUserValidate(AddEditValidateBase):
    id = serializers.IntegerField()

    def validate_id(self, val):
        if not User.objects.filter(id=val).exists():
            raise serializers.ValidationError("编辑对象不存在")
        return val

    def update(self, obj, data):
        roleId = data.pop('roleId', None)
        deptId = data.pop('deptId', None)
        obj = super().update(obj, data)
        if roleId:
            # 获取当前用户已有的角色 ID
            existing_ids = set(obj.userrole_set.values_list('pk', flat=True))

            # 计算需要新增和删除的角色
            new_ids = set(map(lambda x: int(x), roleId))
            to_add = new_ids - existing_ids
            to_remove = existing_ids - new_ids

            # 执行批量操作
            if to_add:
                for i in UserRole.objects.bulk_create([UserRole(user=obj, role_id=id) for id in to_add]):
                    i.save() # 为了触发信号
            if to_remove:
                UserRole.objects.filter(pk__in=to_remove).delete()
        else:
            # 删除关联的所有角色
            UserRole.objects.filter(user=obj).delete()

        if deptId:
            # 获取当前用户已有的部门 ID
            existing_ids = set(obj.userdept_set.values_list('pk', flat=True))

            # 计算需要新增和删除的部门
            new_ids = set(map(lambda x: int(x), deptId))
            to_add = new_ids - existing_ids
            to_remove = existing_ids - new_ids

            # 执行批量操作
            if to_add:
                for i in UserDept.objects.bulk_create([UserDept(user=obj, dept_id=id) for id in to_add]):
                    i.save() # 为了触发信号
            if to_remove:
                UserDept.objects.filter(pk__in=to_remove).delete()
        else:
            # 删除关联的所有部门
            UserDept.objects.filter(user=obj).delete()
        return obj

    class Meta(AddEditValidateBase.Meta):
        exclude = ['password']
        
# 解封验证
class UnlockValidate(serializers.Serializer):
    userIds = serializers.CharField(error_messages={"required":'用户id不能为空'})

    def validate(self, data):
        userIds = [int(id) for id in data['userIds'].split()]
        if User.objects.filter(id__in=userIds).count() != len(userIds):
            raise serializers.ValidationError('部分用户不存在')
        data['userIds'] = userIds
        return data
    
    def update(self, data):
        User.objects.only('is_active').filter(id__in=data['userIds']).update(is_active=0)
        return True

# 重置密码
class ResetPasswordValidate(serializers.Serializer):
    userIds = serializers.CharField(error_messages={"required":'用户id不能为空'})
    
    def validate(self, data):
        userIds = [int(id) for id in data['userIds'].split()]
        if User.objects.filter(id__in=userIds).count() != len(userIds):
            raise serializers.ValidationError('部分用户不存在')
        data['userIds'] = userIds
        return data
    
    def update(self, data):
        users = User.objects.only('id').filter(id__in=data['userIds'])
        for user in users:
            user.set_password('123456')   # 默认密码123456
            user.save()
        return True
    
# 给用户分配角色验证
class GrantValidate(serializers.Serializer):
    userId = serializers.IntegerField(error_messages={"required":'用户id不能为空'})
    roleIds = serializers.CharField(required=False, allow_blank=True)

    def validate(self, data):
        roleId = data['userId']
        roleIds = data.get('roleIds','').split(',')
        if not User.objects.filter(id=roleId).exists():
            raise serializers.ValidationError("用户不存在")
        roleIds = [int(i) for i in roleIds]
        if Role.objects.filter(id__in=roleIds).count() != len(roleIds):
            raise serializers.ValidationError('部分角色不存在')
        data['roleIds'] = roleIds
        return data
    
    def create(self, data):
        userId = data['userId']
        UserRole.objects.filter(role_id=userId).delete()
        user_roles = [UserRole(user_id=userId, role_id=id) for id in data['roleIds']]
        UserRole.objects.bulk_create(user_roles)
        return True

# 用户专用修改用户基本信息验证类
class UpdateInfoValidateBase(BSerializer):
    name = serializers.CharField(max_length=255, required=False)
    
    class Meta:
        model = User
        exclude = ['id', 'account', 'password', 'is_active']

# 修改用户密码验证
class UpdatePasswordValidateBase(serializers.Serializer):
    oldPassword = serializers.CharField(max_length=255)
    newPassword = serializers.CharField(max_length=255)
    newPassword1 = serializers.CharField(max_length=255)
    
    def validate(self, data):
        oldPassword = data['oldPassword']
        newPassword = data['newPassword']
        newPassword1 = data['newPassword1']
        
        if newPassword != newPassword1:
            raise ValidationError("两次输入密码不一致")
        if not self.context['user'].check_password(oldPassword):
            raise ValidationError("原密码错误")
        return data
    
    # 修改密码
    def updatePassword(self, validated_data):
        user = self.context['user']
        user.set_password(validated_data['newPassword'])
        user.save()

